// Copyright (c) [Year] [name of copyright holder]
// [Software Name] is licensed under Mulan PSL v2.
// You can use this software according to the terms and conditions of the Mulan PSL v2. 
// You may obtain a copy of Mulan PSL v2 at:
//          http://license.coscl.org.cn/MulanPSL2 
// THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.  
// See the Mulan PSL v2 for more details.

/*!
 * \autor captainpeng
 * \date 2019-11-3
 * \update 2019-11-3
 * \version 1.0
 * \copyright
 */

#ifndef MY_TYPETUPLE_HPP
#define MY_TYPETUPLE_HPP

#include"typeDecl.hpp"

namespace my{

    template<int INDEX, typename T, typename ... TYPES>
    struct typeTupleSeq : typeTupleSeq<INDEX + 1, TYPES ...>{
        using curType = T;
        using baseType = typeTupleSeq<INDEX + 1, TYPES ...>;
        using nextType = typename baseType::curType;
        
        static const int index = INDEX;
    };

    template<int INDEX>
    struct typeTupleSeq<INDEX, typeNil>{
        using curType = typeNil;
        static const int index = INDEX;
    };

    template<typename SEQTYPE, int N>
    struct typeTupleSeqGet{
        using type = typename typeTupleSeqGet<typename SEQTYPE::baseType, N - 1>::type;
    };

    template<typename SEQTYPE>
    struct typeTupleSeqGet<SEQTYPE, 0>{
        using type = typename SEQTYPE::curType;
    };

    template<typename ... TYPES>
    struct typeTuple{
        static_assert(sizeof...(TYPES), "typeTuple sizeof...(TYPES) == 0");

        static const int size = sizeof...(TYPES);
        using seqType = typeTupleSeq<0, TYPES ..., typeNil>;

        template<int N>
        using getType = typename typeTupleSeqGet<seqType, N>::type;
    };

    template<typename TUPLE, int INDEX>
    struct typeTupleGet{
        using type = typename typeTupleSeqGet<typename TUPLE::seqType, INDEX>::type;
    };
}

#endif
